#include "QcTestPaperView.h"
#include "KpTestInfo.h" // for KeTestMode
#include "KgTestLogDb.h"
#include "KgMiswordDb.h"

#include <QStyledItemDelegate>
#include <QLineEdit>
#include <QTextToSpeech>
#include <QApplication>
#include <QFile>
#include <QDir>

namespace kPrivate
{
    extern QTextToSpeech* speech;
}

class QcPaperViewItemDelegate : public QStyledItemDelegate
{
    using super_ = QStyledItemDelegate;

public:
    using super_::super_;

    QWidget *createEditor(QWidget* w, const QStyleOptionViewItem&, const QModelIndex& index) const override {
        return new QLineEdit(w);
    }
};

QcTestPaperView::QcTestPaperView(QWidget *parent)
    : QTreeWidget(parent)
{
    setItemDelegateForColumn(2, new QcPaperViewItemDelegate);

    connect(this, &QTreeWidget::itemClicked, this, [this](QTreeWidgetItem* item, int column) {
        if (column == 2 && isColumnHidden(3)/*是否答题状态*/)
            editItem(item, 2); // 始终编辑第1列

        if (column == 1 && info_.mode == KpTestInfo::K_DICTATE)
            kPrivate::speech->say(item->data(3, Qt::DisplayRole).toString());
    });

    connect(&timer_, &QTimer::timeout, this, [this](){
        emit ticked(++info_.ticked);
    });
}

void QcTestPaperView::startTest(const QVector<std::array<QString, 3>>& wordsinfo, int mode)
{
    clear();

    // 隐藏答案和判卷结果
    setColumnHidden(3, true);
    setColumnHidden(4, true);

    // wordsinfo为三维数组 { 英文，中文，音标 }，根据mode映射到列
    int cols1 = -1, cols3 = -1;
    switch(mode) {
    case KpTestInfo::K_DICTATE:
        cols3 = 0; // 音频 -> 英文
        break;

    case KpTestInfo::K_PHONETIC:
        cols1 = 2, cols3 = 0; // 音标 -> 英文
        break;

    case KpTestInfo::K_ENGLISH:
        cols1 = 0, cols3 = 1; // 英文 -> 中文
        break;

    case KpTestInfo::K_CHINESE:
        cols1 = 1, cols3 = 0; // 中文 -> 英文
        break;
    }

    // 生成试卷
    QList<QTreeWidgetItem*> items;
    items.reserve(wordsinfo.size());
    for (auto& i : wordsinfo) {
        auto item = new QTreeWidgetItem(this);
        items.push_back(item);
        item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemNeverHasChildren);
        item->setText(0, QString::number(items.size()));
        if (cols1 != -1) // 题目
            item->setText(1, i[cols1]);
        else
            item->setIcon(1, QIcon(":/main/images/volumn"));

        if (cols3 != -1) // 答案
            item->setText(3, i[cols3]);
    }
    addTopLevelItems(items);
    resizeColumnToContents(0);

    info_.mode = KpTestInfo::KeTestMode(mode);
    info_.startTime = QDateTime::currentDateTime(); // 记录考核开始时间
    info_.ticked = 0;
    info_.amount = wordsinfo.size();
    info_.score = 0;
    timer_.start(1000); // 每秒触发一次考核时间更新
}

int QcTestPaperView::finishTest()
{
    timer_.stop();

    // 显示答案和判卷结果
    setColumnHidden(3, false);
    setColumnHidden(4, false);

    info_.score = 0;
    QTreeWidgetItemIterator it(this);
    while(*it) {
        if (0 == (*it)->text(2).trimmed().compare((*it)->text(3).trimmed(), Qt::CaseInsensitive)) {
            (*it)->setIcon(4, QIcon(":/main/images/bingo")); // 答对图标
            (*it)->setData(4, Qt::UserRole, true);
            ++info_.score;
        }
        else {
            (*it)->setIcon(4, QIcon(":/main/images/missed")); // 答错图标
            (*it)->setData(4, Qt::UserRole, false);
        }
        ++it;
    }

    return info_.score;
}

QString QcTestPaperView::logDir()
{
    return QApplication::applicationDirPath() + "/log";
}

void QcTestPaperView::saveLog()
{
    /// 保存考核历史记录，用于显示成绩榜
    ///
    QDir().mkpath(logDir());
    KgTestLogDb logDb(logDir());
    logDb.appendHistory(info_);

    /// 保存考核详细记录
    ///
    QVector<KgTestLogDb::KpTestDetail> tds; tds.reserve(info_.amount);

    // 按4元组（问题、答题、答案、对错）生成行
    QTreeWidgetItemIterator it(this);
    while(*it) {
        KgTestLogDb::KpTestDetail line;
        line[0] = (info_.mode == KpTestInfo::K_DICTATE) ? "[-]" : (*it)->text(1);
        line[1] = (*it)->text(2);
        line[2] = (*it)->text(3);
        line[3] = (*it)->data(4, Qt::UserRole).toBool() ? "1" : "0";
        tds.append(std::move(line));
        ++it;
    }

    logDb.saveDetails(info_.startTime, tds);


    /// 保存答错记录，用于显示错词榜
    ///
    int wordCol = (info_.mode == KpTestInfo::K_ENGLISH) ? 1 : 3;
    it = QTreeWidgetItemIterator(this);
    KgMiswordDb miswordDb(QcTestPaperView::logDir());
    while(*it) {
        auto wrong = !(*it)->data(4, Qt::UserRole).toBool();
        miswordDb.update(info_, (*it)->text(wordCol), wrong);
        ++it;
    }

    miswordDb.save();
}
